package ;

import easelhx.display.BitmapAnimation;
import easelhx.display.Graphics;
import easelhx.display.Shape;
import easelhx.js.Image;
import easelhx.display.SpriteSheet;
import easelhx.utils.Ticker;

/**
 * ...
 * @author 
 */

class SparklesFadeExample extends Example
{
	var oldX:Float;
	var imgSeq:Image;		// The image for the sparkle animation
	var bmpAnim:BitmapAnimation;		

	public function new() 
	{
		super();
	}
	
	override public function run():Void 
	{
		super.run();
		
		oldX = 0;
		imgSeq = new Image();
		
		// load the sprite sheet image, and wait for it to complete before proceeding:
		imgSeq.onload = handleImageLoad;
		imgSeq.src = "assets/sparkle_21x23.png";
	}
	
	private function handleImageLoad() : Void
	{
		// attach mouse handlers directly to the source canvas.
		// better than calling from canvas tag for cross browser compatibility:
		stage.onMouseMove = moveCanvas;
		stage.onMouseDown = clickCanvas;

		// create a semi-opaque black rectangle that covers the full stage.
		// drawing this to stage each tick will cause the canvas to fade to black.
		var shape:Shape = new Shape(new Graphics().beginFill('#333').drawRect(0,0,canvas.width+1,canvas.height));
		shape.alpha = 0.35;
		stage.addChild(shape);

		// this prevents the stage from automatically clearing itself each tick.
		// in this demo, it results in the star trails, as the previous draws remain on screen.
		stage.autoClear = false;

		// define simple sprite sheet data specifying the image(s) to use, the size of the frames,
		// and the registration point of the frame
		// it will auto-calculate the number of frames from the image dimensions and loop them
		var data = {
			images: ["assets/sparkle_21x23.png"],
			frames: { width:21, height:23, regX:10, regY:11 }
		}

		// set up an animation instance, which we will clone
		bmpAnim = new BitmapAnimation(new SpriteSheet(data));

		// start the tick and point it at the window so we can do some work before updating the stage:
		Ticker.addListener(this);
	}

	private function tick() : Void
	{
		var h = canvas.height;
		var w = canvas.width;

		// loop through all of the active sparkles on stage:
		var l = stage.getNumChildren();
		var i:Int = l - 1;
		while (i > 1) {
			var sparkle = stage.getChildAt(i);

			// apply gravity and friction
			Reflect.setField(sparkle, "vY", Reflect.field(sparkle,"vY") + 2);
			Reflect.setField(sparkle, "vX", Reflect.field(sparkle,"vX") * 0.98);

			// update position, scale, and alpha:
			sparkle.x += Reflect.field(sparkle,"vX");
			sparkle.y += Reflect.field(sparkle,"vY");
			sparkle.alpha += Reflect.field(sparkle,"vA");

			// remove sparkles that are no longer visible or are stalled:
			if (sparkle.alpha <= 0 || sparkle.y >= h && Reflect.field(sparkle, "vY") < 10) {
				stage.removeChildAt(i);
			}
			
			//bounce sparkles off the bottom
			if (sparkle.y > h) {
				untyped sparkle.vY *= -(Math.random() * 0.4 + 0.4);
				sparkle.y -= sparkle.y%h;
			}
			if (sparkle.x >= w || sparkle.x <= 0) {
				untyped sparkle.vX *= -1;
			}
			i--;
		}

		// draw the updates to stage
		stage.update();
	}

	// sparkle explosion
	private function clickCanvas(evt) : Void
	{
		addSparkles(Std.int(Math.random() * 100 + 100) | 0, evt.stageX, evt.stageY, 2, 0);
	}

	//sparkle trail
	private function moveCanvas(evt) : Void
	{
		addSparkles(Std.int(Math.random() * 2 + 1) | 0, evt.stageX, evt.stageY, 1, evt.stageX - oldX);
		oldX = evt.stageX;
	}

	private function addSparkles(count, x, y, speed, velX) : Void
	{
		//create the specified number of sparkles
		for (i in 0...count) 
		{
			// clone the original sparkle, so we don't need to set shared properties:
			var sparkle:BitmapAnimation = cast bmpAnim.clone();

			// set display properties:
			sparkle.x = x;
			sparkle.y = y;
			sparkle.alpha = Math.random()*0.5+0.5;
			sparkle.scaleX = sparkle.scaleY = Math.random()+0.3;
			sparkle.compositeOperation = "lighter";

			// set up velocities:
			var a = Math.PI * 2 * Math.random();
			var v = (Math.random() - 0.5) * 30 * speed;
			untyped sparkle.vX = Math.cos(a) * v + velX;
			untyped sparkle.vY = Math.sin(a) * v;
			untyped sparkle.vA = -Math.random() * 0.05 - 0.01; // alpha
			
			// start the animation on a random frame:
			sparkle.gotoAndPlay(Std.int(Math.random() * sparkle.spriteSheet.getNumFrames()) | 0);

			// add to the display list:
			stage.addChild(sparkle);
		}
	}
	
}